<?php

namespace Rebecca\RebeccaBundle\Component;

require_once "ComponentBase.php";
include_once 'bundles/RebeccaBundle/Plugins/PHPExcel/Classes/PHPExcel/Calculation.php';

use Rebecca\RebeccaBundle\Entity\Liquidaciones;
use Rebecca\RebeccaBundle\Entity\ConceptosLiquidados;
use Rebecca\RebeccaBundle\Entity\TiposNomina;
use Rebecca\RebeccaBundle\Entity\Constantes;
use Rebecca\RebeccaBundle\Entity\ParamertrosRegistrados;
use Rebecca\RebeccaBundle\Entity\Conceptos;
use \Rebecca\RebeccaBundle\Entity\Parametros;

/**
 * Description of LiquidacionesComponent
 *
 * @author Manlio Ferreira
 */
class LiquidacionesComponent extends ComponentBase {

    private $conceptosEncontrados = array();
    private $constantesEncontradas = array();
    private $parametrosEncontrados = array();
    private $idBeneficiarioLibranza;
    private $idBeneficiarioDescuento;
    private $seguir = TRUE;
    private $parametrosUsados = array();
    
    function getPeriodosLiquidados() {
        $liquidaciones = $this->em->getRepository("RebeccaBundle:Liquidaciones")->findAll();
        
        $periodos = array();
        
        foreach ($liquidaciones as $liquidacion){
            if(!in_array($liquidacion->getIdPeriodoLaboral(), $periodos)){
                array_push($periodos, $liquidacion->getIdPeriodoLaboral());
            }
        }
        
        return $periodos;
    }

    function getLiquidacionByIdentificacion($documentoIdentidad, $periodoLaboral) {
        /* @var $trabajador \Rebecca\RebeccaBundle\Entity\Trabajadores */
        $trabajador = $this->em->getRepository("RebeccaBundle:Trabajadores")->findOneBy(array(
            'numeroIdentidad' => $documentoIdentidad
                ));
        
        if(!is_null($trabajador)){
            /* @var $contrato \Rebecca\RebeccaBundle\Entity\Contratos */
            $contrato = $this->em->getRepository("RebeccaBundle:Contratos")->findOneBy(array(
                'idTrabajador' => $trabajador->getId()
                    ));


            /* @var $liquidacion Liquidaciones */
            $liquidacion = $this->em->getRepository($this->entityName)->findOneBy(array(
                'idContrato' => $contrato->getId(),
                'idPeriodoLaboral' => $periodoLaboral
                    ));

            $conceptosLiquidados = $this->em->getRepository("RebeccaBundle:ConceptosLiquidados")->findBy(array(
                'idLiquidacion' => $liquidacion->getId()
                    ));

            $liquidacion->setConceptosLiquidados($conceptosLiquidados);

            return $liquidacion;
        }
        
        return null;
    }

    function getLiquidacionById($id) {
        /* @var $liquidacion Liquidaciones */
        $liquidacion = $this->em->getRepository($this->entityName)->find($id);

        $conceptosLiquidados = $this->em->getRepository("RebeccaBundle:ConceptosLiquidados")->findBy(array(
            'idLiquidacion' => $id
                ));

        $liquidacion->setConceptosLiquidados($conceptosLiquidados);

        return $liquidacion;
    }

    function getConceptosLiquidados($idLiquidacion) {
        return $this->em->getRepository("RebeccaBundle:ConceptosLiquidados")->findBy(array(
                    'idLiquidacion' => $idLiquidacion
                ));
    }

    function verificarPeriodo($idPeriodoLaboral) {
        $result = $this->em->getRepository("RebeccaBundle:Liquidaciones")->findOneBy(array(
            'idPeriodoLaboral' => $idPeriodoLaboral
                ));

        return !is_null($result);
    }

    function getAllConceptosLiquidados() {
        return $this->em->getRepository("RebeccaBundle:ConceptosLiquidados")->findAll();
    }

    function getFullTiposNomina() {
        return $this->em->getRepository("RebeccaBundle:TiposNomina")->findAll();
    }

    function getPeriodosLaboralesByTipoNomina($idTipoNomina) {
        /* @var $periodosLaborales \Rebecca\RebeccaBundle\Entity\PeriodosLaborales */
        $periodosLaborales = $this->em->getRepository("RebeccaBundle:PeriodosLaborales")->findAll();

        $periodos = array();

        foreach ($periodosLaborales as $element /* @var $element \Rebecca\RebeccaBundle\Entity\PeriodosLaborales */) {
            if ($element->getIdPeriodo()->getIdTipoNomina()->getId() == $idTipoNomina) {
                array_push($periodos, $element);
            }
        }

        return $periodos;
    }

    function getConceptos() {
        return $this->em->getRepository("RebeccaBundle:Conceptos")->findAll();
    }

    function getTipoNomina($id) {
        return $this->em->getRepository("RebeccaBundle:TiposNomina")->find($id);
    }

    function getContratos($tipoNomina) {
        return $this->em->getRepository("RebeccaBundle:Contratos")->findBy(
                        array(
                            'idTipoNomina' => $tipoNomina
                ));
    }

    function getPeriodosLaborales() {
        return $this->em->getRepository("RebeccaBundle:PeriodosLaborales")->findAll();
    }

    function generateLiquidaciones($contratos, $fechaLiquidacion, $periodo, $nota, $conceptos) {

        $liquidaciones = array();
        $_periodo = $this->em->getRepository("RebeccaBundle:PeriodosLaborales")->find($periodo);

        foreach ($contratos as $item) {
            $liquidacion = new Liquidaciones();

            /* @var $contrato \Rebecca\RebeccaBundle\Entity\Contratos */
            $contrato = $this->em->getRepository("RebeccaBundle:Contratos")->find($item);

            $liquidacion->setFechaLiquidacion($fechaLiquidacion);
            $liquidacion->setNotas($nota);
            $liquidacion->setIdPeriodoLaboral($_periodo);
            $liquidacion->setIdContrato($contrato);
            $liquidacion->setFechaOperacion(date('d/m/Y'));

            $conceptosLiquidados = array();

            foreach ($conceptos as $itemConcepto) {
                /* @var $concepto Conceptos */
                $concepto = $this->em->getRepository("RebeccaBundle:Conceptos")->find($itemConcepto);
                $formula = $concepto->getFormula();

                if (!empty($formula)) {
                    $formula = $concepto->getFormula();
                    if ($concepto->getIdTipoConcepto()->getId() == 2) {
                        $formula = "-($formula)";
                    }
                    $formula = $this->procesarFormula($formula, $contrato->getId(), $periodo);
                    $concepto->setFormula($formula);

                    $conceptoLiquidado = new ConceptosLiquidados();
                    $conceptoLiquidado->setIdConcepto($concepto);


                    array_push($conceptosLiquidados, clone $conceptoLiquidado);
                }
            }

            $liquidacion->setConceptosLiquidados(clone $conceptosLiquidados);
            array_push($liquidaciones, $liquidacion);

            $this->em->clear();
        }

        return $liquidaciones;
    }

    function generateAllLiquidaciones($fechaLiquidacion, $idPeriodoLaboral, $notas, $save = FALSE) {
        /* @var $periodoLaboral \Rebecca\RebeccaBundle\Entity\PeriodosLaborales */
        $periodoLaboral = $this->em->getRepository("RebeccaBundle:PeriodosLaborales")->find($idPeriodoLaboral);

        $periodosLaboralesContratos = $this->em->getRepository("RebeccaBundle:PeriodosLaboralesContratos")->findBy(
                array(
                    'idPeriodoLaboral' => $idPeriodoLaboral
                ));

        $periodosEnConcepto = $this->em->getRepository("RebeccaBundle:PeriodosEnConceptos")->findBy(
                array(
                    'idPeriodo' => $periodoLaboral->getIdPeriodo()->getId()
                ));

        if (!$save) {
            $this->procesarSalario($idPeriodoLaboral);
            $this->procesarHorasExtra($idPeriodoLaboral);
            $this->procesarBonificaciones($idPeriodoLaboral);
            $this->procesarDeducciones($idPeriodoLaboral);
            $this->procesarVacaciones($idPeriodoLaboral);
            $this->procesarLibranzas($idPeriodoLaboral);
        }

        $liquidaciones = array();

        foreach ($periodosLaboralesContratos as $periodoLaboralContrato /* @var $periodoLaboralContrato \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {
            $liquidacion = new Liquidaciones();

            $liquidacion->setFechaLiquidacion($fechaLiquidacion);
            $liquidacion->setFechaOperacion(date_create());
            $liquidacion->setIdContrato($periodoLaboralContrato->getIdContrato());
            $liquidacion->setIdPeriodoLaboral($periodoLaboralContrato->getIdPeriodoLaboral());
            $liquidacion->setNotas($notas);

            $conceptosLiquidados = array();
            foreach ($periodosEnConcepto as $item /* @var $item \Rebecca\RebeccaBundle\Entity\PeriodosEnConceptos */) {
                $this->seguir = TRUE;
                unset($this->parametrosUsados);
                $this->parametrosUsados = array();

                while ($this->seguir) {
                    /* @var $concepto Conceptos */
                    $concepto = $item->getIdConcepto();

                    $formula = $concepto->getFormula();

                    $formula = $this->procesarFormula($formula, $periodoLaboralContrato->getIdContrato()->getId(), $idPeriodoLaboral);

                    if ($formula != 0) {

                        if ($concepto->getIdTipoConcepto()->getId() == 2) {
                            $formula = -1 * $formula;
                        }
                        $conceptoLiquidado = new ConceptosLiquidados();
                        $conceptoLiquidado->setIdConcepto($concepto);
                        $conceptoLiquidado->setValor($formula);

                        if ($this->idBeneficiarioDescuento) {
                            $beneficiario = $this->em->getRepository("RebeccaBundle:BeneficiariosDescuentos")->find($this->idBeneficiarioDescuento);
                            $conceptoLiquidado->setIdBeneficiarioDescuentos($beneficiario);
                        }
                        if ($this->idBeneficiarioLibranza) {
                            $beneficiario = $this->em->getRepository("RebeccaBundle:BeneficiariosLibranzas")->find($this->idBeneficiarioLibranza);
                            $conceptoLiquidado->setIdBeneficiarioLibranzas($beneficiario);
                        }

                        array_push($conceptosLiquidados, ($conceptoLiquidado));
                        $this->em->clear();
                    }
                }
            }


            $mivariable = $conceptosLiquidados;

            $liquidacion->setConceptosLiquidados($mivariable);

            array_push($liquidaciones, $liquidacion);
            $this->em->clear();
        }

        return $liquidaciones;
    }

    private function procesarHorasExtra($idPeriodoLaboral) {
        $periodosLaborales = $this->em->getRepository("RebeccaBundle:PeriodosLaboralesContratos")->findBy(
                array(
                    'idPeriodoLaboral' => $idPeriodoLaboral
                ));

        /* @var $parametro \Rebecca\RebeccaBundle\Entity\Parametros */
        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(2);

        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {

            /* @var $horasExtra \Rebecca\RebeccaBundle\Entity\HorasExtra */
            $horasExtra = $this->em->getRepository("RebeccaBundle:HorasExtra")->findOneBy(
                    array(
                        'idPeriodoLaboralContrato' => $periodo->getId()
                    ));

            if ($horasExtra != NULL) {

                $parametroRegistrado = new ParamertrosRegistrados();
                $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                $parametroRegistrado->setIdParametro($parametro);
                $parametroRegistrado->setFormula($horasExtra->getDiurnas());

                $this->save($parametroRegistrado);
            }
        }
        $this->commit();

        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(3);
        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {

            /* @var $horasExtra \Rebecca\RebeccaBundle\Entity\HorasExtra */
            $horasExtra = $this->em->getRepository("RebeccaBundle:HorasExtra")->findOneBy(
                    array(
                        'idPeriodoLaboralContrato' => $periodo->getId()
                    ));

            if ($horasExtra != NULL) {

                $parametroRegistrado = new ParamertrosRegistrados();
                $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                $parametroRegistrado->setIdParametro($parametro);
                $parametroRegistrado->setFormula($horasExtra->getNocturnas());

                $this->save($parametroRegistrado);
            }
        }
        $this->commit();

        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(8);
        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {

            /* @var $horasExtra \Rebecca\RebeccaBundle\Entity\HorasExtra */
            $horasExtra = $this->em->getRepository("RebeccaBundle:HorasExtra")->findOneBy(
                    array(
                        'idPeriodoLaboralContrato' => $periodo->getId()
                    ));

            if ($horasExtra != NULL) {

                $parametroRegistrado = new ParamertrosRegistrados();
                $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                $parametroRegistrado->setIdParametro($parametro);
                $parametroRegistrado->setFormula($horasExtra->getFestivas());

                $this->save($parametroRegistrado);
            }
        }
        $this->commit();

        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(9);
        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {

            /* @var $horasExtra \Rebecca\RebeccaBundle\Entity\HorasExtra */
            $horasExtra = $this->em->getRepository("RebeccaBundle:HorasExtra")->findOneBy(
                    array(
                        'idPeriodoLaboralContrato' => $periodo->getId()
                    ));

            if ($horasExtra != NULL) {

                $parametroRegistrado = new ParamertrosRegistrados();
                $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                $parametroRegistrado->setIdParametro($parametro);
                $parametroRegistrado->setFormula($horasExtra->getExtrasFestivas());

                $this->save($parametroRegistrado);
            }
        }
        $this->commit();

        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(10);
        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {

            /* @var $horasExtra \Rebecca\RebeccaBundle\Entity\HorasExtra */
            $horasExtra = $this->em->getRepository("RebeccaBundle:HorasExtra")->findOneBy(
                    array(
                        'idPeriodoLaboralContrato' => $periodo->getId()
                    ));

            if ($horasExtra != NULL) {

                $parametroRegistrado = new ParamertrosRegistrados();
                $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                $parametroRegistrado->setIdParametro($parametro);
                $parametroRegistrado->setFormula($horasExtra->getNocturnasFestivas());

                $this->save($parametroRegistrado);
            }
        }
        $this->commit();
    }

    private function procesarVacaciones($idPeriodoLaboral) {
        $periodosLaborales = $this->em->getRepository("RebeccaBundle:PeriodosLaboralesContratos")->findBy(
                array(
                    'idPeriodoLaboral' => $idPeriodoLaboral
                ));

        /* @var $parametro \Rebecca\RebeccaBundle\Entity\Parametros */
        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(16);

        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {

            /* @var $vacaciones \Rebecca\RebeccaBundle\Entity\Vacaciones */
            $vacaciones = $this->em->getRepository("RebeccaBundle:Vacaciones")->findOneBy(
                    array(
                        'idPeriodoLaboralContrato' => $periodo->getId()
                    ));

            if ($vacaciones != NULL) {

                $parametroRegistrado = new ParamertrosRegistrados();
                $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                $parametroRegistrado->setIdParametro($parametro);
                $parametroRegistrado->setFormula('1');

                $this->save($parametroRegistrado);
            }
        }
        $this->commit();
    }

    private function procesarBonificaciones($idPeriodoLaboral) {
        $periodosLaborales = $this->em->getRepository("RebeccaBundle:PeriodosLaboralesContratos")->findBy(
                array(
                    'idPeriodoLaboral' => $idPeriodoLaboral
                ));

        /* @var $parametro \Rebecca\RebeccaBundle\Entity\Parametros */
        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(13);

        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {

            $bonificaciones = $this->em->getRepository("RebeccaBundle:Bonificaciones")->findBy(
                    array(
                        'idPeriodoLaboralContrato' => $periodo->getId()
                    ));

            if ($bonificaciones != NULL) {
                foreach ($bonificaciones as $bonificacion /* @var $bonificaciones \Rebecca\RebeccaBundle\Entity\Bonificaciones */) {

                    $parametroRegistrado = new ParamertrosRegistrados();
                    $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                    $parametroRegistrado->setIdParametro($parametro);
                    $parametroRegistrado->setFormula($bonificacion->getValor());

                    $this->save($parametroRegistrado);
                }
            }
        }
        $this->commit();
    }

    /* @var $libranza \Rebecca\RebeccaBundle\Entity\Libranzas */

    private function procesarLibranzas($idPeriodoLaboral) {
        $periodosLaborales = $this->em->getRepository("RebeccaBundle:PeriodosLaboralesContratos")->findBy(
                array(
                    'idPeriodoLaboral' => $idPeriodoLaboral
                ));

        $myPeriodoLaboral = $this->em->getRepository("RebeccaBundle:PeriodosLaborales")->find($idPeriodoLaboral);

        $libranzas = $this->em->getRepository("RebeccaBundle:Libranzas")->findAll();

        foreach ($libranzas as $libranza) {
            //if ($libranza->getSaldo() > 0) {
            $libranzaLiquidada = new \Rebecca\RebeccaBundle\Entity\LibranzasLiquidadas();

            $monto = $libranza->getCuota() < $libranza->getSaldo() || $libranza->getMonto() == 0 ? $libranza->getCuota() : $libranza->getSaldo();

            $cuotas = $this->em->getRepository("RebeccaBundle:LibranzasLiquidadas")->findBy(
                    array(
                        'idLibranza' => $libranza->getId()
                    ));

            $numeroCuota = count($cuotas);
            $libranzaLiquidada->setCuota($numeroCuota + 1);
            $libranzaLiquidada->setIdLibranza($libranza);
            $libranzaLiquidada->setFechaCreacion(date_create());
            $libranzaLiquidada->setMonto(round($monto, -2));
            $libranzaLiquidada->setIdPeriodoLaboral($myPeriodoLaboral);

            $this->save($libranzaLiquidada);

            if ($libranza->getSaldo() != 0) {
                $libranza->setSaldo(round(($libranza->getSaldo() - $libranzaLiquidada->getMonto()), -2));

                $this->update($libranza);
            }
            // }
        }
        $this->commit();
        /* @var $parametro \Rebecca\RebeccaBundle\Entity\Parametros */
        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(6);

        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {

            $libranzas = $this->em->getRepository("RebeccaBundle:LibranzasLiquidadas")->findBy(
                    array(
                        'idPeriodoLaboral' => $idPeriodoLaboral
                    ));

            if ($libranzas != NULL) {
                /* @var $libranzaLiquidada \Rebecca\RebeccaBundle\Entity\LibranzasLiquidadas */
                foreach ($libranzas as $libranzaLiquidada) {
                    if ($libranzaLiquidada->getIdLibranza()->getIdContrato()->getId() == $periodo->getIdContrato()->getId()) {
                        $parametroRegistrado = new ParamertrosRegistrados();
                        $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                        $parametroRegistrado->setIdParametro($parametro);
                        $parametroRegistrado->setFormula($libranzaLiquidada->getMonto());
                        $parametroRegistrado->setIdBeneficiarioLibranzas($libranzaLiquidada->getIdLibranza()->getIdBeneficiario());

                        $this->save($parametroRegistrado);
                    }
                }
            }
        }
        $this->commit();
    }

    private function procesarDeducciones($idPeriodoLaboral) {
        $periodosLaborales = $this->em->getRepository("RebeccaBundle:PeriodosLaboralesContratos")->findBy(
                array(
                    'idPeriodoLaboral' => $idPeriodoLaboral
                ));

        /* @var $parametro \Rebecca\RebeccaBundle\Entity\Parametros */
        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(14);

        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {

            $descuentos = $this->em->getRepository("RebeccaBundle:Descuentos")->findBy(
                    array(
                        'idPeriodoLaboralContrato' => $periodo->getId()
                    ));

            if ($descuentos != NULL) {
                foreach ($descuentos as $descuento /* @var $descuento \Rebecca\RebeccaBundle\Entity\Descuentos */) {


                    $gt = new \Rebecca\RebeccaBundle\Entity\Descuentos();


                    $parametroRegistrado = new ParamertrosRegistrados();
                    $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                    $parametroRegistrado->setIdParametro($parametro);

                    $parametroRegistrado->setIdBeneficiarioDescuentos($descuento->getIdBeneficiario());

                    if ($descuento->getTipo() == 1) {
                        $parametroRegistrado->setFormula($descuento->getValor());
                    } else {
                        /* @var $trabajadorEnVacante \Rebecca\RebeccaBundle\Entity\TrabajadoresEnVacante */
                        $trabajadorEnVacante = $this->em->getRepository("RebeccaBundle:TrabajadoresEnVacantes")->find(
                                array(
                                    'idTrabajador' => $periodo->getIdContrato()->getIdTrabajador()->getId(),
                                    'activo' => TRUE
                                ));
                        $parametroRegistrado->setFormula($descuento->getValor() * $trabajadorEnVacante->getIdVacante()->getSalario());
                    }

                    $this->save($parametroRegistrado);
                }
            }
        }
        $this->commit();
    }

    private function procesarSalario($idPeriodoLaboral) {
        $periodosLaborales = $this->em->getRepository("RebeccaBundle:PeriodosLaboralesContratos")->findBy(
                array(
                    'idPeriodoLaboral' => $idPeriodoLaboral
                ));

        /* @var $parametro \Rebecca\RebeccaBundle\Entity\Parametros */
        $parametro = $this->em->getRepository("RebeccaBundle:Parametros")->find(1);

        foreach ($periodosLaborales as $periodo /* @var $periodo \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */) {
            $trabajador = $periodo->getIdContrato()->getIdTrabajador();

            /* @var $trabajadorEnVacante \Rebecca\RebeccaBundle\Entity\TrabajadoresEnVacantes */
            $trabajadorEnVacante = $this->em->getRepository("RebeccaBundle:TrabajadoresEnVacantes")->find(
                    array(
                        'idTrabajador' => $trabajador->getId(),
                        'activo' => TRUE
                    ));

            if ($trabajadorEnVacante != NULL) {
                $parametroRegistrado = new ParamertrosRegistrados();
                $parametroRegistrado->setIdPeriodosLaboralesContratos($periodo);
                $parametroRegistrado->setIdParametro($parametro);

                $parametroRegistrado->setFormula($trabajadorEnVacante->getIdVacante()->getSalario());

                $this->save($parametroRegistrado);
            }
        }
        $this->commit();
    }

    private function procesarFormula($formula, $contrato, $periodoLaboral) {

        while (strpos($formula, "_CONCE")) {
            $formula = $this->procesarConceptos($formula);
        }

        $formula = $this->procesarConstantes($formula, $contrato, $periodoLaboral);
        $formula = $this->procesarParametros($formula, $contrato, $periodoLaboral);

        $formula = $this->calcularFormula($formula);

        return $formula;
    }

    private function procesarConceptos($formula) {
        $conceptos = array();
        preg_match_all("/_CONCE\([_A-Z0-9]*\)/i", $formula, $conceptos);
        $conceptos = $conceptos[0];

        foreach ($conceptos as $value) {

            $length = strpos($value, ")") - 7;
            $abreviatura = substr($value, 7, $length);

            /* @var $concepto Conceptos */
            $concepto = $this->findConceptosByAbreviatura($abreviatura);

            $valorConcepto = $concepto->getFormula();
            $valorConcepto = !empty($valorConcepto) ? $valorConcepto : "0";

            $formula = str_replace($value, "($valorConcepto)", $formula);
        }

        return $formula;
    }

    private function procesarParametros($formula, $contrato, $periodoLaboral) {
        $parametros = array();
        preg_match_all("/_PARAM\([_A-Z0-9]*\)/i", $formula, $parametros);
        $parametros = $parametros[0];

        if (count($parametros) == 0) {
            $this->seguir = FALSE;
        } else {
            foreach ($parametros as $value) {

                $length = strpos($value, ")") - 7;
                $abreviatura = substr($value, 7, $length);

                /* @var $parametro \Rebecca\RebeccaBundle\Entity\Parametros */
                $parametro = $this->findParametrosByAbreviatura($abreviatura);

                $parametroRegistrado = $this->getParametroRegistrado($parametro->getId(), $contrato, $periodoLaboral, TRUE);

                if ($parametroRegistrado) {
                    $valorParametro = $parametroRegistrado->getFormula();
                    $this->idBeneficiarioDescuento = $parametroRegistrado->getIdBeneficiarioDescuentos() ? $parametroRegistrado->getIdBeneficiarioDescuentos()->getId() : NULL;
                    $this->idBeneficiarioLibranza = $parametroRegistrado->getIdBeneficiarioLibranzas() ? $parametroRegistrado->getIdBeneficiarioLibranzas()->getId() : NULL;
                } else {
                    $valorParametro = "0";
                }

                $formula = str_replace($value, "({$this->zeroOnEmpty($valorParametro)})", $formula);
            }
        }

        return $formula;
    }

    private function procesarConstantes($formula, $contrato, $periodoLaboral) {

        $constantes = array();
        preg_match_all("/_CONS\([_A-Z0-9]*\)/i", $formula, $constantes);

        $constantes = $constantes[0];

        foreach ($constantes as $value) {
            $length = strpos($value, ")") - 6;

            $abreviatura = substr($value, 6, $length);

            /* @var $constante Constantes */
            $constante = $this->findConstantesByAbreviatura($abreviatura);

            if ($constante->getEsRelacionado()) {
                //Si esta linea no funciona, comentenla y descomenten las lineas que le siguen.
                $parametroRegistrado = $this->getParametroRegistrado($constante->getIdParametro()->getId(), $contrato, $periodoLaboral);
                $valorParametro = $parametroRegistrado ? $parametroRegistrado->getFormula() : "0";

                $formula = str_replace($value, "({$this->zeroOnEmpty($valorParametro)})", $formula);
            } else {
                $formula = str_replace($value, "({$this->zeroOnEmpty($constante->getValor())})", $formula);
            }
        }

        return $formula;
    }

    private function calcularFormula($formula) {

        try {
            $formula = \PHPExcel_Calculation::getInstance()->calculateFormula('=' . $formula);
        } catch (\Exception $exc) {
            return $formula;
        }


        return $formula;
    }

    function deepSave($liquidaciones) {
        foreach ($liquidaciones as $liquidacion /* @var $liquidacion Liquidaciones */) {
            $liquidacion->setIdPeriodoLaboral($this->em->getRepository("RebeccaBundle:PeriodosLaborales")->find($liquidacion->getIdPeriodoLaboral()->getId()));
            $liquidacion->setIdContrato($this->em->getRepository("RebeccaBundle:Contratos")->find($liquidacion->getIdContrato()->getId()));
            $liquidacion->setFechaLiquidacion(\DateTime::createFromFormat("d/m/Y", $liquidacion->getFechaLiquidacion()));
            $liquidacion->setFechaOperacion(new \DateTime());

            $this->save($liquidacion);
            $this->commit();

            $conceptosLiquidados = $liquidacion->getConceptosLiquidados();

            foreach ($conceptosLiquidados as $item /* @var $item ConceptosLiquidados */) {
                $item->setIdLiquidacion($liquidacion);
                $item->setIdConcepto($this->em->getRepository("RebeccaBundle:Conceptos")->find(( $item->getIdConcepto()->getId())));

                if ($item->getIdBeneficiarioDescuentos()) {
                    $item->setIdBeneficiarioDescuentos($this->em->getRepository("RebeccaBundle:BeneficiariosDescuentos")->find(( $item->getIdBeneficiarioDescuentos()->getId())));
                } else {
                    $item->setIdBeneficiarioDescuentos(NULL);
                }
                if ($item->getIdBeneficiarioLibranzas()) {
                    $item->setIdBeneficiarioLibranzas($this->em->getRepository("RebeccaBundle:BeneficiariosLibranzas")->find(( $item->getIdBeneficiarioLibranzas()->getId())));
                } else {
                    $item->setIdBeneficiarioLibranzas(NULL);
                }

                //  try {
                $this->save($item);

//                } catch (\Exception $exc) {
//                    var_dump($item);
//                    die;
//                }
            }
            $this->commit();
        }
    }

    /**
     *
     * @param type $idParametro
     * @param type $contrato
     * @param type $periodoLaboral
     * @return \Rebecca\RebeccaBundle\Entity\ParamertrosRegistrados 
     */
    private function getParametroRegistrado($idParametro, $contrato, $periodoLaboral, $registrar = false) {

        /* @var $periodoLaboralContrato \Rebecca\RebeccaBundle\Entity\PeriodosLaboralesContratos */

        $periodoLaboralContrato = $this->em->getRepository("RebeccaBundle:PeriodosLaboralesContratos")->findOneBy(
                array(
                    'idContrato' => $contrato,
                    'idPeriodoLaboral' => $periodoLaboral
                ));

        $parametrosRegistrados = $this->em->getRepository("RebeccaBundle:ParamertrosRegistrados")->findBy(
                array(
                    'idParametro' => $idParametro,
                    'idPeriodosLaboralesContratos' => $periodoLaboralContrato->getId()
                ));

        //TODO: Arreglar esta logica de negocio
        if ($registrar) {
            $my_array = array();

            foreach ($parametrosRegistrados as $element /* @var $element ParamertrosRegistrados */) {
                $contains = FALSE;

                foreach ($this->parametrosUsados as $value /* @var $value ParamertrosRegistrados */) {
                    if ($value->getId() == $element->getId())
                        $contains = TRUE;
                }
                if (!$contains)
                    array_push($my_array, $element);
            }

            $parametrosRegistrados = $my_array;

            if (count($parametrosRegistrados) <= 1) {
                $this->seguir = FALSE;
            } else {
                array_push($this->parametrosUsados, $parametrosRegistrados[0]);
            }
        }

        if (count($parametrosRegistrados) == 0)
            return NULL;
        else
            return $parametrosRegistrados[0];
    }

    private function zeroOnEmpty($value) {
        return !empty($value) ? $value : "0";
    }

    /**
     * Para usos futuros.
     * 
     * @param type $type
     * @param type $formula
     * @return type 
     */
    private function getAbreviaturas($type, $formula) {
        $abreviaturas = array();
        preg_match_all("/_$type\([_A-Z0-9]*\)/i", $formula, $abreviaturas);

        $abreviaturas = $abreviaturas[0];

        foreach ($abreviaturas as $i => $abreviatura) {
            $typeLen = strlen("_$type") + 1;
            $length = strpos($abreviatura, ")") - $typeLen;
            $abreviaturas[$i] = substr($abreviatura, $typeLen, $length);
        }

        return $abreviaturas;
    }

    /**
     *
     * @param string $abreviatura
     * @return Conceptos 
     */
    private function findConceptosByAbreviatura($abreviatura) {
        if (!isset($this->conceptosEncontrados[$abreviatura])) {
            $this->conceptosEncontrados[$abreviatura] = $this->em->getRepository("RebeccaBundle:Conceptos")->findOneBy(array("abreviatura" => $abreviatura,));
        }

        return $this->conceptosEncontrados[$abreviatura];
    }

    /**
     *
     * @param string $abreviatura
     * @return Constantes 
     */
    private function findConstantesByAbreviatura($abreviatura) {
        if (!isset($this->constantesEncontradas[$abreviatura])) {
            $this->constantesEncontradas[$abreviatura] = $this->em->getRepository("RebeccaBundle:Constantes")->findOneBy(array("abreviatura" => $abreviatura,));
        }

        return $this->constantesEncontradas[$abreviatura];
    }

    /**
     *
     * @param string $abreviatura
     * @return Parametros 
     */
    private function findParametrosByAbreviatura($abreviatura) {
        if (!isset($this->parametrosEncontrados[$abreviatura])) {
            $this->parametrosEncontrados[$abreviatura] = $this->em->getRepository("RebeccaBundle:Parametros")->findOneBy(array("abreviatura" => $abreviatura,));
        }

        return $this->parametrosEncontrados[$abreviatura];
    }

}

?>
